
import SwiftUI
import RealityKit
import Combine // For Cancellable
import UIKit
struct ImmersiveFactoryView: View {
    @EnvironmentObject var appState: AppState
    @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace

    // State for gesture tracking within this view might be needed if
    // direct binding to appState proves complex or causes too many updates.
    // However, using AppState directly promotes single source of truth.

    var body: some View {
        RealityView { content, attachments in
            // --- MAKE: Called once when the view appears ---
            print("RealityView Make: Loading model for type: \(appState.currentModelType)")

            // 1. 清理旧内容 (如果需要，但 RealityView update 通常会处理)
             content.remove(appState.rootEntity)

            // 2. 重建根实体 (或重用 appState.rootEntity)
             appState.rootEntity = Entity() // 创建新的或清空旧的
             appState.rootEntity.name = "RootTransformNode"

            // 3. 加载模型
            Task {
                 guard let modelName = appState.currentModelType.modelName else {
                     print("No model name specified.")
                     // Maybe load a placeholder?
                     let placeholder = ModelEntity(mesh: .generateBox(size: 0.5), materials: [SimpleMaterial(color: .red, isMetallic: false)])
                     placeholder.name = "Placeholder"
                     appState.modelEntity = placeholder
                     setupModelEntity(placeholder) // 配置加载的模型
                     return
                 }

                 do {
                     print("Attempting to load model: \(modelName).usdz")
                     // 异步加载模型
                     //let loadedEntity = try await ModelEntity(named: "\(modelName).usdz")
                     let loadedEntity = try await ModelEntity(named: "\(modelName)")
                     loadedEntity.name = modelName // 给实体命名，便于查找
                     print("Model \(modelName) loaded successfully.")
                     appState.modelEntity = loadedEntity
                     setupModelEntity(loadedEntity) // 配置加载的模型

                 } catch {
                     print("Error loading model \(modelName): \(error)")
                     // 加载失败，显示占位符
                     let placeholder = ModelEntity(mesh: .generateSphere(radius: 0.3), materials: [SimpleMaterial(color: .yellow, isMetallic: false)])
                     placeholder.name = "ErrorPlaceholder"
                     appState.modelEntity = placeholder
                    setupModelEntity(placeholder)
                 }
            }

            // 4. 添加根实体到场景
             content.add(appState.rootEntity)

            // --- END MAKE ---

        } update: { content, attachments in
             // --- UPDATE: Called whenever state changes ---
             print("RealityView Update: Applying state changes. Current type: \(appState.currentModelType)")

             // 1. 应用变换
             // 确保模型实体存在并且已添加到 rootEntity 中
             if appState.modelEntity != nil && appState.modelEntity?.parent == appState.rootEntity {
                 // 应用存储在 AppState 中的变换
                 appState.rootEntity.transform = appState.modelTransform
                 // print("Applied transform: S=\(appState.modelTransform.scale), R=\(appState.modelTransform.rotation)")
             } else if appState.modelEntity != nil && appState.modelEntity?.parent == nil {
                 // 如果模型已加载但尚未添加到场景（可能在 make 的 Task 完成前 update 被调用）
                 // 确保它被添加
                  // setupModelEntity 会处理添加
                  print("Model entity exists but not in parent yet, setupModelEntity should handle.")
             }


            // 2. 处理屋顶动画 (仅当是工厂模型时)
            if case .factory = appState.currentModelType, let factoryModel = appState.modelEntity {
                handleRoofAnimation(model: factoryModel)
                handleLighting(model: factoryModel) // 处理内外灯光/材质
            } else if appState.isRoofLifted {
                 // 如果不是工厂模型了，确保屋顶状态被重置 (虽然 resetModelStateForNewLoad 应该已经做了)
                 appState.isRoofLifted = false
            }

            // 3. 处理工作站隔离 (仅当是工作站模型时)
            if case .workstation(_, let workstationName) = appState.currentModelType, let internalModel = appState.modelEntity {
                 isolateWorkstation(model: internalModel, workstationName: workstationName)
            } else if let model = appState.modelEntity, model.children.contains(where: { !$0.isEnabled }) {
                 // 如果不再是工作站模式，确所有部分都可见
                 showAllParts(model: model)
            }


            // 4. 更新附加的 SwiftUI 视图 (控制面板)
            if let controlPanel = attachments.entity(for: "controlPanel") {
                // 可以将控制面板放置在相对于用户头部或某个固定的世界位置
                 controlPanel.position = [0.8, -0.3, -1.5] // 示例：用户右前方稍低位置
                // 或者附加到模型旁边
                 // controlPanel.position = appState.rootEntity.position + SIMD3<Float>(0.5, 0, 0)
                if controlPanel.parent == nil { // 确保只添加一次
                    content.add(controlPanel)
                }
            }
             // --- END UPDATE ---

        } attachments: {
            // 定义附加的 SwiftUI 视图
            Attachment(id: "controlPanel") {
                 ControlPanelView()
                    .environmentObject(appState) // 传递状态
                    .frame(width: 200, height: 250) // 给面板一个尺寸
                    .glassBackgroundEffect()
            }
        }
        // --- Gestures ---
        .gesture(SpatialTapGesture()
            .targetedToAnyEntity() // 允许点击场景中的任何实体
            .onEnded { value in
                let tappedEntity = value.entity
                print("Tapped entity: \(tappedEntity.name)")

                // 根据点击的实体和当前状态执行操作
                switch appState.currentModelType {
                case .factory:
                    // 检查是否点击了屋顶 (假设屋顶实体名为 "FactoryRoof")
                    if tappedEntity.findEntity(named: "FactoryRoof") != nil || tappedEntity.name == "FactoryRoof" {
                         appState.handleTapOnRoof()
                    } else if !appState.isRoofLifted {
                         print("Tapped on factory base while roof is closed.")
                         // 在屋顶关闭时点击工厂其他部分可能无操作，或根据需要添加
                    }
                    else {
                        // 屋顶已打开，点击内部区域，切换到内部模型
                         print("Tapped inside factory, switching to internal view.")
                         appState.showInternalModel()
                     }
                case .internalModel:
                    // 点击内部模型的某个部分，判断是否为工作站，然后切换
                    // 需要您定义如何识别工作站实体（例如，通过名称）
                    let workstationName = determineWorkstationName(from: tappedEntity)
                    if let name = workstationName {
                        appState.showWorkstation(name)
                    } else {
                         print("Tapped on internal model part, but not identified as a workstation.")
                    }
                case .workstation:
                    // 在工作站视图中点击可能无操作，或用于显示详细信息
                    print("Tapped on workstation model: \(tappedEntity.name)")
                case .generic, .none:
                    print("Tap detected on generic model or in empty space.")
                }
            }
        )
        .simultaneousGesture(DragGesture() // 使用 simultaneousGesture 避免干扰 Tap
            .onChanged { value in
                // --- 旋转逻辑 ---
                let dragSensitivity: Float = 0.005 // 调整灵敏度
                let deltaX = Float(value.translation.width) * dragSensitivity
                let deltaY = Float(value.translation.height) * dragSensitivity

                // 围绕 Y 轴旋转 (左右拖动)
                let rotationY = simd_quatf(angle: -deltaX, axis: SIMD3<Float>(0, 1, 0))
                // 围绕 X 轴旋转 (上下拖动) - 注意轴向可能需要根据模型朝向调整
                let rotationX = simd_quatf(angle: -deltaY, axis: SIMD3<Float>(1, 0, 0))

                // 将新的旋转应用到手势开始时的旋转状态上
                let combinedRotationDelta = simd_normalize(rotationY * rotationX)
                appState.modelTransform.rotation = simd_normalize(combinedRotationDelta * appState.startRotation)

                // 更新位置（如果需要拖动移动物体，取消注释下一行）
                // let worldTranslation = SIMD3<Float>(Float(value.translation.width) * 0.001, Float(value.translation.height) * -0.001, 0)
                // appState.modelTransform.translation = appState.initialModelTransform.translation + worldTranslation // 移动基于初始位置

                // print("Dragging: R=\(appState.modelTransform.rotation)")
            }
            .onEnded { value in
                // 手势结束，更新下一次拖动的起始旋转状态
                appState.startRotation = appState.modelTransform.rotation
                print("Drag ended. Stored start rotation: \(appState.startRotation)")
            }
        )
        .simultaneousGesture(MagnifyGesture() // 缩放手势
            .onChanged { value in
                // --- 缩放逻辑 ---
                 // 基于手势开始时的缩放比例和当前的放大倍数计算新比例
                let newScaleFactor = appState.startScale * Float(value.magnification)
                // 限制最小和最大缩放比例
                let clampedScale = max(0.1, min(5.0, newScaleFactor)) // 示例：限制在 0.1 到 5.0 之间
                 appState.modelTransform.scale = SIMD3<Float>(repeating: clampedScale)
                 // print("Magnifying: S=\(appState.modelTransform.scale)")
            }
            .onEnded { value in
                // 手势结束，更新下一次缩放的起始比例
                 appState.startScale = appState.modelTransform.scale.x // 假设统一缩放
                 print("Magnify ended. Stored start scale: \(appState.startScale)")
            }
        )
        .onAppear {
            print("ImmersiveFactoryView Appeared.")
             // 确保 isImmersiveSpaceShown 与实际状态同步
             appState.isImmersiveSpaceShown = true
        }
        .onDisappear {
             print("ImmersiveFactoryView Disappeared.")
             // 用户可能通过系统手势关闭了空间
             if appState.isImmersiveSpaceShown { // 检查是否是预期之外的关闭
                 print("Immersive space closed unexpectedly, returning to main menu.")
                 appState.isImmersiveSpaceShown = false
                 appState.currentModelType = .none
                 // 可以在这里决定是返回主菜单还是工厂选择
                  appState.currentScreen = .mainMenu // 或者 .factorySelection
             }
        }
        .onChange(of: appState.isImmersiveSpaceShown) { _, isShown in
             // 当 AppState 请求关闭时，执行 dismiss
             if !isShown {
                 Task {
                     print("Dismissing immersive space via AppState request.")
                     await dismissImmersiveSpace()
                 }
             }
         }
         .onChange(of: appState.currentModelType) { _, newType in
             // 当模型类型改变时 (例如从工厂切换到内部)，确保视图重新加载
             // RealityView 的 update 会被触发，我们可以在那里处理模型加载逻辑
             print("Model type changed to \(newType), RealityView will update.")
             // 注意：重置模型状态 (resetModelStateForNewLoad) 应该在触发类型改变的函数 (如 showInternalModel) 中调用
         }
    }

    // --- Helper Functions ---

    // 配置加载的模型实体
    private func setupModelEntity(_ entity: ModelEntity) {
         // 1. 生成碰撞形状以进行点击检测
         entity.generateCollisionShapes(recursive: true)
         print("Generated collision shapes for \(entity.name)")

         // 2. 将模型添加到根变换节点
         appState.rootEntity.addChild(entity)
         print("Added \(entity.name) to rootEntity")

         // 3. 记录初始变换 (必须在添加到父节点之后获取正确的初始世界变换，或者用局部变换)
         // 如果模型有初始偏移或旋转，记录下来
         // 这里我们假设加载后模型位于 (0,0,0)，无旋转，缩放为 1
         // 如果不是，需要获取 entity.transform *after* adding it to root,
         // 或者如果模型文件本身就有变换，记录那个。
         // 为了简单，我们假设初始状态是 identity
         appState.initialModelTransform = appState.rootEntity.transform // 根节点的初始变换通常是 identity
         appState.modelTransform = appState.initialModelTransform // 设置当前变换为初始值

         // 4. 重置手势起始状态
         appState.startScale = appState.initialModelTransform.scale.x
         appState.startRotation = appState.initialModelTransform.rotation
         print("Stored initial transform and reset gesture starts.")

         // 5. 初始灯光/材质设置
         handleLighting(model: entity)
         // 6. 如果是工作站模式，立即隔离
         if case .workstation(_, let workstationName) = appState.currentModelType {
             isolateWorkstation(model: entity, workstationName: workstationName)
         }
        // 7. 如果是工厂模式，检查屋顶初始状态
         if case .factory = appState.currentModelType {
             handleRoofAnimation(model: entity) // 应用初始屋顶状态
         }
    }


    // 处理屋顶升降动画和消失
    private func handleRoofAnimation(model: ModelEntity) {
        guard let roofEntity = model.findEntity(named: "FactoryRoof") else {
             print("Warning: Could not find entity named 'FactoryRoof'.")
             return
         }

         let targetPosition: SIMD3<Float> = appState.isRoofLifted ? [0, 1, 0] : [0, 0, 0] // 上升 1 米或归位 (相对位置)
         let targetOpacity: Float = appState.isRoofLifted ? 0.0 : 1.0 // 升起后透明度为 0

         // 使用 RealityKit 动画或直接设置 transform 和 material
         if let transformComponent = roofEntity.components[Transform.self] {
             // 直接设置位置 (无动画，因为 SwiftUI 的 withAnimation 控制外部状态)
             var newTransform = transformComponent // 获取当前变换
             newTransform.translation = targetPosition // 修改相对位置
             roofEntity.transform = newTransform // 应用新变换

             // 控制可见性/透明度 (需要 PBR Material 或 UnlitMaterial)
              setVisibility(for: roofEntity, isVisible: !appState.isRoofLifted, recursive: true) // 使用启用/禁用来完全隐藏
             // 或者修改材质透明度 (如果材质支持)
              // setOpacity(for: roofEntity, opacity: targetOpacity, recursive: true)

             print("Roof \(roofEntity.name) position set to \(targetPosition), visible: \(!appState.isRoofLifted)")
         }
    }

    // 处理模型内外亮度变化
    private func handleLighting(model: ModelEntity) {
        // 实现逻辑：
        // 1. 找到代表外部和内部的实体或材质。
        // 2. 如果屋顶升起 (appState.isRoofLifted is true):
        //    - 降低外部实体的材质亮度/颜色 或 应用较暗的材质。
        //    - 提高内部实体的材质亮度/颜色 或 应用较亮的材质。
        // 3. 如果屋顶放下:
        //    - 恢复外部和内部的默认材质/亮度。

        // 示例 (需要根据你的模型结构调整):
        let exteriorMaterial = SimpleMaterial(color: appState.isRoofLifted ? .darkGray : .gray, isMetallic: false)
         let interiorMaterial = SimpleMaterial(color: appState.isRoofLifted ? .lightGray.withAlphaComponent(1.0) : .gray.withAlphaComponent(0.8), isMetallic: false) // 内部可能略微透明

        if let exteriorPart = model.findEntity(named: "FactoryExterior") {
             if var modelComp = exteriorPart.components[ModelComponent.self] {
                 modelComp.materials = [exteriorMaterial]
                 exteriorPart.components.set(modelComp)
             }
        }
        if let interiorPart = model.findEntity(named: "FactoryInterior") {
             if var modelComp = interiorPart.components[ModelComponent.self] {
                 modelComp.materials = [interiorMaterial]
                 interiorPart.components.set(modelComp)
             }
        }
         print("Lighting adjusted based on roof state.")
    }

    // 根据名称隐藏除指定工作站外的所有其他部分
    private func isolateWorkstation(model: ModelEntity, workstationName: String) {
         print("Isolating workstation: \(workstationName)")
         // 遍历模型的所有直接子实体 (假设工作站是模型的直接子节点)
         for child in model.children {
             if child.name == workstationName {
                 child.isEnabled = true // 显示目标工作站
                 print("Showing: \(child.name)")
             } else {
                 child.isEnabled = false // 隐藏其他部分
                 print("Hiding: \(child.name)")
             }
         }
     }

     // 显示模型的所有部分
     private func showAllParts(model: ModelEntity) {
         print("Showing all parts of the model.")
         for child in model.children {
             child.isEnabled = true
         }
     }


    // 辅助函数：确定点击的实体是否代表一个工作站
    private func determineWorkstationName(from entity: Entity) -> String? {
        // 向上遍历实体层级，查找具有特定命名模式的父实体
        var currentEntity: Entity? = entity
        while let e = currentEntity {
             // 假设工作站实体的命名约定是 FactoryName_WorkstationName
             // 或者有特定的组件标识它们
            if e.name.contains("_WS_") || e.name.starts(with: "Workstation") { // 示例命名约定
                 return e.name // 返回第一个匹配的父实体名称
             }
            currentEntity = e.parent
        }
        return nil // 没有找到匹配的工作站实体
    }

    // 辅助函数：递归设置实体的可见性 (启用/禁用)
     private func setVisibility(for entity: Entity, isVisible: Bool, recursive: Bool) {
         entity.isEnabled = isVisible
         if recursive {
             for child in entity.children {
                 setVisibility(for: child, isVisible: isVisible, recursive: true)
             }
         }
     }

     // 辅助函数：递归设置实体的透明度 (如果材质支持)
    private func setOpacity(for entity: Entity, opacity: Float, recursive: Bool) {
//        guard var modelComponent = entity.components[ModelComponent.self] else {
//            return // 没有模型组件可以修改
//        }
//
//        var newMaterials: [RealityKit.Material] = []
//
//        for material in modelComponent.materials {
//            var newMaterial: RealityKit.Material
//
//            if let pbr = material as? PhysicallyBasedMaterial {
//                // 处理 PhysicallyBasedMaterial 的透明度
//                var newPBR = pbr
//                if case let .color(color) = pbr.baseColor {
//                    newPBR.baseColor = .color(color.opacity(Double(opacity)))
//                }
//                newMaterial = newPBR
//            } else if let simple = material as? SimpleMaterial {
//                // 处理 SimpleMaterial 的透明度
//                var newSimple = simple
//                newSimple.color = .init(tint: colorOpacity(color: simple.color, opacity: opacity))
//                newMaterial = newSimple
//            } else if let unlit = material as? UnlitMaterial {
//                // 处理 UnlitMaterial 的透明度
//                var newUnlit = unlit
//                newUnlit.color = .init(tint: colorOpacity(color: unlit.color, opacity: opacity))
//                newMaterial = newUnlit
//            } else {
//                // 对于其他材质类型，直接应用透明度调整（如果可能）
//                newMaterial = material
//            }
//
//            newMaterials.append(newMaterial)
//        }
//
//        modelComponent.materials = newMaterials
//        entity.components.set(modelComponent)
//
//        if recursive {
//            for child in entity.children {
//                setOpacity(for: child, opacity: opacity, recursive: true)
//            }
//        }
    }

    // 辅助函数：调整颜色透明度
    private func colorOpacity(color: SwiftUI.Color, opacity: Float) -> SwiftUI.Color {
        return color.opacity(Double(opacity))
    }
}
